﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

using PGMHelper;
using WSAP;

namespace CouplingBeamProject
{
    /// <summary>
    /// 组件基类
    /// </summary>
    class ComponentBasic
    {
        /// <summary>
        /// 楼层编号
        /// </summary>
        public int StoreyID { set; get; }

        /// <summary>
        /// 左墙宽度
        /// </summary>
        protected double LeftWallWidth { set; get; }

        /// <summary>
        /// 右墙宽度
        /// </summary>
        protected double RightWallWidth { set; get; }

        /// <summary>
        /// 中梁宽度
        /// </summary>
        protected double MiddleBeamWidth { set; get; }

        /// <summary>
        /// 中梁高度
        /// </summary>
        public double MiddleBeamHeight { set; get; }

        /// <summary>
        /// 层高
        /// </summary>
        public double StoreyHeight { set; get; }

        /// <summary>
        /// 单元列表
        /// </summary>
        public List<Block> BlockElementList { set; get; }

        /// <summary>
        /// 等效弹模放大倍数
        /// </summary>
        public double MiddlebeamModulusFactor { set; get; }

        /// <summary>
        /// 添加单元
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool AddElements(WModelNet model)
        {
            foreach (var block in this.BlockElementList)
            {
                if (!block.AddElements(model))
                    return false;
            }
            return true;
        }

        /// <summary>
        /// 顶部增加刚性杆
        /// </summary>
        /// <param name="model"></param>
        /// <param name="targetNodeList"></param>
        /// <returns></returns>
        public void AddRigidFrames(WModelNet model, List<Node> targetNodeList)
        {
            //最高节点高度
            var ymax = (from node in this.GetNodeList() select node.Y).ToList().Max();
            //获得顶部节点
            var topNodeList = targetNodeList.Find("Y", ymax);
            //节点排序
            topNodeList.OrderBy("X");
            //添加单元
            for(int nodeIndex = 0; nodeIndex < topNodeList.Count - 1; nodeIndex++)
            {
                var beam = model.AddRectConcreteBeam(topNodeList[nodeIndex].Index, topNodeList[nodeIndex + 1].Index, GlobalVar.Thickness, this.StoreyHeight);
                beam.SetReleaseType(FrameReleaseEnum.IJRelease);
            }
        }

        /// <summary>
        /// 获得组件高度
        /// </summary>
        /// <returns></returns>
        public double GetHeight()
        {
            return this.StoreyHeight;
        }

        ///// <summary>
        ///// 单元划分方法
        ///// </summary>
        //public virtual void Mesh(double Yoffset)
        //{
        //    return;
        //}

        /// <summary>
        /// 单元划分方法
        /// </summary>
        public virtual void Mesh(double Yoffset, double MiddleBeamThicknessFactor)
        {
            return;
        }

        /// <summary>
        /// 获得单层所有块体的节点
        /// </summary>
        public List<Node> GetNodeList()
        {
            var nodeList = new List<Node>();
            this.BlockElementList.ForEach(block => nodeList.AddRange(block.GetNodeList()));
            return nodeList;
        }

        /// <summary>
        /// 添加节点荷载
        /// </summary>
        public void AddNodeLoad(WModelNet model, List<Node> targetNodeList ,double loadFactor)
        {
            var nodeList = this.GetNodeList();
            var ymax = (from node in nodeList select node.Y).ToList().Max();
            var topNodeList = targetNodeList.Find("Y", ymax);
            topNodeList.ForEach(node => model.AddNodeLoad(node.Index, 1, loadFactor * node.Y / topNodeList.Count));
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="leftWallWidth"></param>
        /// <param name="rightWallWidth"></param>
        /// <param name="middleBeamWidth"></param>
        /// <param name="middleBeamHeigth"></param>
        /// <param name="storeyHeight"></param>
        public ComponentBasic(int storeyid, double leftWallWidth, double middleBeamWidth,
            double rightWallWidth, double middleBeamHeigth, double storeyHeight)
        {
            this.StoreyID = storeyid;
            this.LeftWallWidth = leftWallWidth;
            this.RightWallWidth = rightWallWidth;
            this.MiddleBeamWidth = middleBeamWidth;
            this.MiddleBeamHeight = middleBeamHeigth;
            this.StoreyHeight = storeyHeight;
            this.MiddlebeamModulusFactor = 1;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="basic"></param>
        public ComponentBasic(ComponentBasic basic)
        {
            this.StoreyID = basic.StoreyID;
            this.LeftWallWidth = basic.LeftWallWidth;
            this.RightWallWidth = basic.RightWallWidth;
            this.MiddleBeamWidth = basic.MiddleBeamWidth;
            this.MiddleBeamHeight = basic.MiddleBeamHeight;
            this.StoreyHeight = basic.StoreyHeight;
            this.MiddlebeamModulusFactor = 1;
        }
    }

    /// <summary>
    /// 联肢剪力墙
    /// </summary>
    class CoupledShearWall : ComponentBasic
    {
        /// <summary>
        /// 重写等效模型单元列表
        /// </summary>
        public override void Mesh(double Yoffset, double MiddleBeamThicknessFactor)
        {
            var Concrete = new Material(GlobalVar.ConcreteYoungsModulus , GlobalVar.ConcretePossionRatio);
            var EquivalConcrete = new Material(GlobalVar.ConcreteYoungsModulus * this.MiddlebeamModulusFactor, GlobalVar.ConcretePossionRatio);
            //构造五个矩形块体
            this.BlockElementList = new List<Block>
            {
                //new Block(1, this.LeftWallWidth, this.StoreyHeight - this.MiddleBeamHeight, 0, Yoffset,Concrete),
                new Block(2, this.LeftWallWidth, this.MiddleBeamHeight, 0,
                this.StoreyHeight - this.MiddleBeamHeight + Yoffset,Concrete),
                //new Block(3, this.MiddleBeamWidth, this.MiddleBeamHeight, this.LeftWallWidth,
                //this.StoreyHeight - this.MiddleBeamHeight + Yoffset,EquivalConcrete),//等效弹模

                //new Block(3, this.MiddleBeamWidth, this.MiddleBeamHeight, this.LeftWallWidth,
                //this.StoreyHeight - this.MiddleBeamHeight + Yoffset,EquivalConcrete, MiddleBeamThicknessFactor),//只修改联肢剪力墙中间梁宽度

                new Block(4, this.RightWallWidth, this.MiddleBeamHeight,
                this.LeftWallWidth + this.MiddleBeamWidth, this.StoreyHeight - this.MiddleBeamHeight + Yoffset,Concrete),
                //new Block(5, this.RightWallWidth, this.StoreyHeight - this.MiddleBeamHeight,
                //this.LeftWallWidth + this.MiddleBeamWidth, Yoffset,Concrete),

                new Block(6, 30, this.MiddleBeamHeight, this.LeftWallWidth,
                this.StoreyHeight - this.MiddleBeamHeight + Yoffset, Concrete, MiddleBeamThicknessFactor),
                new Block(8, this.MiddleBeamWidth - 30 - 30, this.MiddleBeamHeight,
                this.LeftWallWidth + 30,this.StoreyHeight - this.MiddleBeamHeight + Yoffset, Concrete, MiddleBeamThicknessFactor),
                new Block(11, 30, this.MiddleBeamHeight, this.LeftWallWidth + this.MiddleBeamWidth - 30,
                this.StoreyHeight - this.MiddleBeamHeight + Yoffset, Concrete, MiddleBeamThicknessFactor),

                new Block(1, this.LeftWallWidth, 20, 0, Yoffset, Concrete),
                new Block(2, this.LeftWallWidth, this.StoreyHeight - this.MiddleBeamHeight - 20,
                0, 20 + Yoffset, Concrete),
                new Block(12, this.RightWallWidth, 20,
                this.LeftWallWidth + this.MiddleBeamWidth, Yoffset, Concrete),
                new Block(13, this.RightWallWidth, this.StoreyHeight - this.MiddleBeamHeight - 20,
                this.LeftWallWidth + this.MiddleBeamWidth, 20 + Yoffset, Concrete),

                // new Block(15, this.MiddleBeamWidth - 30 - 30, this.StoreyHeight - this.MiddleBeamHeight - 20,
                //this.LeftWallWidth + 30, 20 + Yoffset, Concrete)
            };
            //遍历剖分
            this.BlockElementList.ForEach(block => block.Mesh());
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="leftWallWidth"></param>
        /// <param name="rightWallWidth"></param>
        /// <param name="middleBeamWidth"></param>
        /// <param name="middleBeamHeigth"></param>
        /// <param name="storeyHeight"></param>
        public CoupledShearWall(int storeyid, double leftWallWidth, double middleBeamWidth,
            double rightWallWidth, double middleBeamHeigth, double storeyHeight)
            : base(storeyid, leftWallWidth, middleBeamWidth, rightWallWidth, middleBeamHeigth, storeyHeight)
        {
            //this.MiddlebeamModulusFactor = 1;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public CoupledShearWall(ComponentBasic basic, double middleBeamHeigth)
            : base(basic)
        {
            this.MiddleBeamHeight = middleBeamHeigth;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public CoupledShearWall(ComponentBasic basic, double middleBeamHeigth, double middlebeamModulusFactor)
            : base(basic)
        {
            this.MiddleBeamHeight = middleBeamHeigth;
            this.MiddlebeamModulusFactor = middlebeamModulusFactor;
        }
    }

    /// <summary>
    /// 带拉缝填充墙
    /// </summary>
    class CoupledShearWallWithInfill : ComponentBasic
    {
        /// <summary>
        /// 左边填充墙宽度
        /// </summary>
        private double LeftInfillWidth { set; get; }

        /// <summary>
        /// 右边填充墙宽度
        /// </summary>
        private double RightInfillWidth { set; get; }

        /// <summary>
        /// 底部填充墙高度
        /// </summary>
        private double DownInfillHeight { set; get; }

        /// <summary>
        /// 重写原模型单元列表
        /// </summary>
        public override void Mesh(double Yoffset, double MiddleBeamThicknessFactor)
        {
            var Concrete = new Material(CouplingBeamProject.GlobalVar.ConcreteYoungsModulus , CouplingBeamProject.GlobalVar.ConcretePossionRatio);
            var HorizontalSeam = new Material(CouplingBeamProject.GlobalVar.HorizontalSeamYoungsModulus, CouplingBeamProject.GlobalVar.HPossionRatio);
            var VerticalSeam = new Material(CouplingBeamProject.GlobalVar.VerticalSeamYoungsModulus , CouplingBeamProject.GlobalVar.VPossionRatio);
            //构造14个矩形块体
            this.BlockElementList = new List<Block>
            {
                new Block(1, this.LeftWallWidth, this.DownInfillHeight, 0, Yoffset, Concrete),
                new Block(2, this.LeftWallWidth, this.StoreyHeight - this.MiddleBeamHeight - this.DownInfillHeight,
                0, this.DownInfillHeight + Yoffset, Concrete),
                new Block(3, this.LeftWallWidth, this.MiddleBeamHeight, 0, this.StoreyHeight - this.MiddleBeamHeight + Yoffset,Concrete, 1),
                new Block(4, this.LeftInfillWidth, this.DownInfillHeight, this.LeftWallWidth, Yoffset, HorizontalSeam),
                new Block(5, this.LeftInfillWidth, this.StoreyHeight - this.MiddleBeamHeight - this.DownInfillHeight,
                this.LeftWallWidth, this.DownInfillHeight + Yoffset, VerticalSeam),
                new Block(6, this.LeftInfillWidth, this.MiddleBeamHeight, this.LeftWallWidth,
                this.StoreyHeight - this.MiddleBeamHeight + Yoffset, Concrete),
                new Block(7, this.MiddleBeamWidth - this.LeftInfillWidth - this.RightInfillWidth, this.DownInfillHeight,
                this.LeftWallWidth + this.LeftInfillWidth, Yoffset, HorizontalSeam),
                new Block(8, this.MiddleBeamWidth - this.LeftInfillWidth - this.RightInfillWidth, this.MiddleBeamHeight,
                this.LeftWallWidth + this.LeftInfillWidth,this.StoreyHeight - this.MiddleBeamHeight + Yoffset, Concrete),
                new Block(9, this.RightInfillWidth, this.DownInfillHeight,
                this.LeftWallWidth + this.MiddleBeamWidth - this.RightInfillWidth, Yoffset, HorizontalSeam),
                new Block(10, this.RightInfillWidth, this.StoreyHeight - this.MiddleBeamHeight - this.DownInfillHeight,
                this.LeftWallWidth + this.MiddleBeamWidth - this.RightInfillWidth, this.DownInfillHeight + Yoffset, VerticalSeam),
                new Block(11, this.RightInfillWidth, this.MiddleBeamHeight, this.LeftWallWidth + this.MiddleBeamWidth - this.RightInfillWidth,
                this.StoreyHeight - this.MiddleBeamHeight + Yoffset, Concrete),
                new Block(12, this.RightWallWidth, this.DownInfillHeight,
                this.LeftWallWidth + this.MiddleBeamWidth, Yoffset, Concrete),
                new Block(13, this.RightWallWidth, this.StoreyHeight - this.MiddleBeamHeight - this.DownInfillHeight,
                this.LeftWallWidth + this.MiddleBeamWidth, this.DownInfillHeight + Yoffset, Concrete),
                new Block(14, this.RightWallWidth, this.MiddleBeamHeight,
                this.LeftWallWidth + this.MiddleBeamWidth, this.StoreyHeight - this.MiddleBeamHeight + Yoffset, Concrete),
                new Block(15, this.MiddleBeamWidth - this.LeftInfillWidth - this.RightInfillWidth, this.StoreyHeight - this.MiddleBeamHeight - this.DownInfillHeight,
                this.LeftWallWidth + this.LeftInfillWidth, this.DownInfillHeight + Yoffset, Concrete)
            };
            //遍历剖分
            this.BlockElementList.ForEach(block => block.Mesh());
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="leftWallWidth"></param>
        /// <param name="middleBeamWidth"></param>
        /// <param name="rightWallWidth"></param>
        /// <param name="middleBeamHeigth"></param>
        /// <param name="storeyHeight"></param>
        /// <param name="leftInfillWidth"></param>
        /// <param name="RightInfillWidth"></param>
        /// <param name="DownInfillHeight"></param>
        public CoupledShearWallWithInfill(int storeyid, double leftWallWidth, double middleBeamWidth, double rightWallWidth, double middleBeamHeigth,
            double storeyHeight, double leftInfillWidth, double rightInfillWidth, double downInfillHeight)
            : base(storeyid, leftWallWidth, middleBeamWidth, rightWallWidth, middleBeamHeigth, storeyHeight)
        {
            this.LeftInfillWidth = leftInfillWidth;
            this.RightInfillWidth = rightInfillWidth;
            this.DownInfillHeight = downInfillHeight;
        }
    }
}
